<template>
  <div class="container-lg main" id="activitydata">
    <!-- <el-button @click="download">下载</el-button> -->
    <div class="row m-0" :style="{ backgroundImage: `url(${imgs[jianchatime(activity).text]})` }">
      <div class="col co-1">
        <h2 :style="{
          fontWeight: 700,
        }" class="title">{{ activity.name }}</h2>
        <div class="time">结束时间：{{ TimeYH(activity.activityendtime) }}</div>
      </div>
      <div class="col-2 text-right">
        <h2 :style="{
          fontWeight: 700,
        }" class="title"></h2>
        <el-button @click="download2">下载成绩</el-button>
      </div>
    </div>
    <div class="row m-0">
      <div class="col co-1">
        <ul class="nav nav-tabs">
          <li :class="index === 2 ? 'nav-item-active' : ''" @click="setindex(2)" class="nav-item">
            <span class="nav-link" href="#">得分排行</span>
          </li>
          <li :class="index === 3 ? 'nav-item-active' : ''" v-if="!activity.isduplicate" @click="setindex(3)"
            class="nav-item">
            <span class="nav-link" href="#">比赛代码查重</span>
          </li>
        </ul>
      </div>
    </div>
    <div class="row" :style="{
      marginLeft: '48px',
      marginRight: '48px',
    }">
      <div class="col" :style="{
        backgroundColor: '#fff',
        minHeight: '65vh',
        paddingLeft: '24px',
        paddingRight: '24px',
        paddingBottom: '24px'
      }">
        <div :style="{ color: '#434343', fontSize: '12px', marginTop: '12px' }">注：{{ index === 3 ?
          '1）系统采用智能化查重方式，不止比较代码文本，还会根据代码语义进行智能判断；2）只对有获得得分的代码进行查重，查重结果相似度极高的代码会在这里展示。' :
          '若比赛过程中，该排行题号为非真实题号。'
        }}</div>

        <table class="table" v-show="index === 3" :style="{ marginBottom: '0px', marginTop: '24px' }">
          <tr>
            <th v-for="(v, key) in bodykey.index.filter(e => e.index.includes(index))" :key="`${key}_index`"
              :style="v.style" :width="v.width" scope="col">{{ v.name }}</th>
          </tr>
        </table>
        <el-collapse accordion v-show="index === 3" v-model="index_1" :style="{ width: '100%' }">
          <el-collapse-item class="el-collapse-item" v-for="(t, i) in body2" :name="i">
            <template #title>
              <table class="table" :style="{ marginBottom: 0 }">
                <tbody>
                  <tr>
                    <th width="200" :style="{ borderBottomWidth: '0' }">{{ t?.user?.name }}</th>
                    <td width="100" v-show="[0, 1, 2, 3].includes(index)" :style="{ borderBottomWidth: '0' }">{{ t?.df
                    }}
                    </td>
                    <td scope="col" :style="{ borderBottomWidth: '0' }">{{ t?.teams?.join(',') }}</td>
                    <td width="200" v-show="[0, 1, 2].includes(index)" :style="{ borderBottomWidth: '0' }">{{
                      TimeYH(t?.createdAt)
                    }}</td>
                  </tr>
                </tbody>
              </table>
            </template>
            <div>
              <table class="table mb-0" :style="{ marginBottom: 0 }">
                <tbody>
                  <tr v-for="(v, e) in t?.list" :key="i + '_' + e">
                    <th width="100" :style="{ borderBottomWidth: '0px' }">第{{ !isNaN(v.index) ? v.index + 1 : e + 1 }}题
                    </th>
                    <td width="100" v-show="[0, 1, 2].includes(index)" :style="{ borderBottomWidth: '0px' }">
                      {{ v.df }}
                    </td>
                    <td width="100" v-show="[0, 1, 2].includes(index)" :style="{ borderBottomWidth: '0px' }">
                      <div class="div1" :class="v.result">{{ v.resultdata }}</div>
                    </td>
                    <td v-show="[0, 1, 2].includes(index)" :style="{ borderBottomWidth: '0px' }">
                      <div v-if="Array.isArray(v.resultdataarr)">
                        <span v-for="(m, n) in v.resultdataarr" class="span1" :key="i + '_' + e + '_' + n"
                          :class="ALLTYPE[m][1]">{{
                          m }}</span>
                      </div>
                    </td>

                    <td v-if="index === 3" :style="{ borderBottomWidth: '0px' }">
                      <span v-for="(code, key) in v.code" :key="`code_${key}`" class="a-down" target="_blank"
                        @click.stop="dowmload1({ userid: code.ID, questionid: v.questionid, name: code?.name }, { userid: t.user?.ID, questionid: v.questionid, name: t.user?.name })">{{
                          code.name
                        }}</span>
                    </td>
                  </tr>
                </tbody>
              </table>

            </div>


          </el-collapse-item>
        </el-collapse>

        <el-table v-show="index != 3" :data="body3" style="width: 100%;">
          <el-table-column type="index" width="80" label="排名" fixed sortable />
          <el-table-column prop="name" label="用户名称" fixed width="160">
            <template #default="scope">
              {{ scope.row.name }} {{ scope.row.xingming ? scope.row.name ===
                scope.row.xingming ? '' : `(${scope.row.xingming})` : '' }}
            </template>
          </el-table-column>
          <el-table-column prop="updatedAt" label="提交时间" width="160" sortable>
            <template #default="scope">
              {{ TimeYH(scope.row.createdAt) }}
            </template>
          </el-table-column>

          <el-table-column prop="df" label="总分" width="100" sortable>
            <template #default="scope">
              <div class="text-center" :class="className2(scope.row)">
                {{ scope.row.df }}</div>
            </template>
          </el-table-column>
          <el-table-column v-for="(item, key) in matchquestion" :prop="String(key)" :label="`第${key + 1}题`"
            class-name="el-table-column text-center" sortable>
            <template #default="scope">
              <el-tooltip v-if="iswatchcode || isAdmin || scope.row.userid === user?.ID" class="box-item" effect="light"
                content="查看代码" placement="top">
                <div :class="className(scope.row, item, key)" class="cu text-center" @click="getcode(scope.row, item)">
                  {{ scope.row[String(key)] }}</div>
              </el-tooltip>
              <div v-else :class="className(scope.row, item, key)" class="text-center">
                {{ scope.row[String(key)] }}
              </div>
            </template>
          </el-table-column>
        </el-table>
        <div v-show="index === 3 && img" :style="{ textAlign: 'center' }">
          <div class="alert">
            <svg class="icon" aria-hidden="true" v-show="img === 2">
              <use xlink:href="#icon-Clock_filled"></use>
            </svg>
            <svg class="icon" aria-hidden="true" v-show="img === 1">
              <use xlink:href="#icon-Shape"></use>
            </svg>
            &nbsp;
            &nbsp;
            {{ img === 2 ? '代码查重将会在比赛结束后约2-3h内完成' : '本次比赛查重完成没有相似代码' }}
          </div>
          <img
            :src="img === 1 ? 'https://cdn.hterobot.com/JOY/oj_1_1/bisaidaimachachong_chachongwancheng.png' : 'https://cdn.hterobot.com/JOY/oj_1_1/bisaidaimachachong_zhengzaichachong.png'"
            width="480" />
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ElMessage } from "element-plus";
import { encode, encodeURI } from 'js-base64';
import { assign } from "underscore";
import {
  computed,
  onBeforeUnmount,
  onMounted,
  reactive,
  ref,
  watch,
} from "vue";
import { useStore } from "vuex";
import { asyncgetactivity, asyncgetsim, asyncgetusermatchcode, asyncselectmatchquestion, asyncselectmatchranking, asyncteamselectmatchuserquestion, ISIM } from "../../../api";
import { Storekey } from "../../../interface";
import Studycodemodel from "../../../mysql_interface/studycodemodel";
import { getExceltodownload } from "../../../util/excel";
import { ALLTYPE, jianchatime } from "@/util/jianchatime";
import { TimeYH } from "../../../util/time";


const bodykey = {
  index: [
    { index: [0, 1, 2, 3], name: '姓名', width: '200', style: { borderColor: 'var(--color-43)', padding: '20px 12px' } },
    { index: [0, 1, 2], name: '当前得分', width: '100', style: { borderColor: 'var(--color-43)', padding: '20px 12px' }, },
    { index: [3], name: '总得分', width: '100', style: { borderColor: 'var(--color-43)', padding: '20px 12px' }, },
    { index: [0, 1, 2], name: '团队名称', style: { borderColor: 'var(--color-43)', padding: '20px 12px' } },
    { index: [0, 1, 2], name: '提交时间', width: '200', style: { borderColor: 'var(--color-43)', padding: '20px 12px' } },
    { index: [3], name: '编程题代码高度相似数', style: { borderColor: 'var(--color-43)', padding: '20px 12px' }, },
  ],
  title: [
    { index: [0, 1, 2, 3], name: '题号', width: '100', },
    { index: [0, 1, 2], name: '得分', width: '100' },
    { index: [0, 1, 2], name: '状态', width: '100', className: 'text-center' },
    { index: [0, 1, 2], name: '测试点信息', },
    { index: [3], name: '高度相似(相似度>85%)' },
    { index: [3], name: '下载源码', width: '100', className: 'text-center' },
  ]
}

const index_1 = ref()

const limit = ref(1000)
const offset = ref(0)



const p = defineProps<{ ID: number }>()
const store = useStore(Storekey);
const team = computed(() => {
  return store.state.team?.rows || []
})
const user = computed(() => {
  return store.state.user
})
const isAdmin = computed(() => {
  return user.value?.isAdmin || user.value?.remarks == "销售助教"
})
const iswatchcode = computed(() => {
  return activity.iswatchcode
})
const index = ref(2);

const users = ref<Studycodemodel.Iuser[]>([])

const activity = reactive<Studycodemodel.Iactivity>({});
const body = ref<Studycodemodel.Imatchranking[]>([]);




const body3 = computed(() => {
  const data = matchquestion.value.map(e => e.name)
  return users.value.map(f => {
    let k: Record<string | number, string | number | any[]> = {}
    const { ID } = f
    const matchranking = body.value.find(e => e.userid === ID)
    const _data = JSON.parse(matchranking?.data || '') as any[]
    for (const v in data) {
      const d = _data.find(z => z[2] === data[v])
      const f = d ? d[1] : 0
      k[String(v)] = f ? f : 0
    }
    k.resultdata = _data.map(e => e[3]).filter(e => e === 'AC').length === _data.length ? 'AC' : 'UN'
    return {
      ...k,
      ...f,
      ...matchranking
    }
  }).sort((a, b) => Number(b.df) - Number(a.df))
})


const body2 = computed(() => {
  const { users, data } = sim.value
  return users.sort((a, b) => {
    const adf = body.value.find(z => z.userid == a.ID)
    const bdf = body.value.find(z => z.userid == b.ID)
    return Number(bdf?.df) - Number(adf?.df)
  }).map(e => {
    const { ID } = e
    const adf = body.value.find(z => z.userid == ID)
    const t = data[String(ID)]
    if (t) {
      const code = matchquestion.value.filter(e => {
        return Object.keys(t).includes(String(e.ID))
      }).map(z => {
        const e = t[String(z.ID)] || []
        const code = e.map(z => {
          const [userid, fen] = z
          const user = users.find(t => t.ID === Number(userid))
          return assign({}, user, { name: `${user?.name} (相似度 ${fen}%)` })
        })
        return {
          index: z.paixu,
          questionid: z.ID,
          code
        }
      })
      return {
        df: adf?.df,
        user: e,
        list: code,
        teams: [`${code.length}题`]
      }
    }
  })
})


async function start() {
  if (p.ID) {
    const data = await asyncgetactivity({ ID: p.ID });
    Object.assign(activity, data);
  }
}

const sim = ref<ISIM>({ users: [], data: {} })

const matchquestion = ref<Studycodemodel.Imatchquestion[]>([])

async function selectmatchquestion() {
  const [data] = await asyncselectmatchquestion({ activityid: p.ID })
  matchquestion.value = data.matchquestion || []
}

const img = ref(1)

async function getsim() {
  asyncgetsim({ activityid: p.ID }).then(e => {
    sim.value = e
    if (Object.keys(e.data).length) {
      img.value = 0
    }
  }).catch(e => {
    img.value = 2;
    console.log(e)
  })
}


async function getbody() {
  const { user, matchranking } = await asyncselectmatchranking({ activityid: p.ID, _offset: offset.value, _limit: limit.value, _order: 'df', _sortable: 'DESC' })
  users.value = user
  if (activity.isranking) {
    body.value = matchranking
  }

}

onMounted(async () => {
  // 进入房间
  await start();
  store.state.socket.emit("activity", { activityid: p.ID, com: true });
  store.state.socket.on("activity", () => {
    if (activity.isranking) {
      getbody()
    }
  });
  getsim()
  selectmatchquestion()
});

function className(params: Studycodemodel.Imatchranking, matchquestion: Studycodemodel.Imatchquestion, index: number) {
  const { data } = params
  const _data = JSON.parse(data || '[]') as any[]
  const n = _data[index]
  const c = n[1] / Number(matchquestion.score)
  if (c >= 0.7) {
    return 'Accepted'
  } else if (c >= 0.3) {
    return 'Unaccepted'
  } else {
    return 'CompileError'
  }
}

function className2(params: Studycodemodel.Imatchranking) {
  const { df } = params
  const c = Number(df) / Number(matchquestion.value.map(a => Number(a.score)).reduce((c, d) => Number(c) + Number(d)), 0)
  if (c >= 0.7) {
    return 'Accepted'
  } else if (c >= 0.3) {
    return 'Unaccepted'
  } else {
    return 'CompileError'
  }
}


function setindex(i: number) {
  index.value = i;
}

watch(() => index.value, () => {
  index_1.value = ''
})

onBeforeUnmount(() => {
  store.state.socket.emit("activity", { activityid: p.ID, com: false });
});


const imgs: Record<string, string> = {
  即将开赛:
    "https://cdn-hterobot.oss-cn-qingdao.aliyuncs.com/JOY/oj_1_1/jo_1_1_homepage/baiomingzhuangtai_weikaishi.svg",
  立即报名:
    "https://cdn-hterobot.oss-cn-qingdao.aliyuncs.com/JOY/oj_1_1/jo_1_1_homepage/baiomingzhuangtai_baomingzhong.svg",
  进入比赛:
    "https://cdn-hterobot.oss-cn-qingdao.aliyuncs.com/JOY/oj_1_1/jo_1_1_homepage/baiomingzhuangtai_bisaizhong.svg",
  赛事结束:
    "https://cdn-hterobot.oss-cn-qingdao.aliyuncs.com/JOY/oj_1_1/jo_1_1_homepage/baiomingzhuangtai_bisaijieshu.svg",
}




async function dowmload1(body: { userid: number, questionid: number, name: string }, body2?: { userid: number, questionid: number, name: string }) {
  const [data] = await asyncgetusermatchcode({ userid: body.userid, questionid: body.questionid, activityid: p.ID })
  let data2 = ['', '.cpp']
  const d = data[0].split('.')[1]
  let language = 'cpp'
  if (d === 'py') {
    language = 'python'
  }

  if (body2) {
    const [_data2] = await asyncgetusermatchcode({ userid: body2.userid, questionid: body2.questionid, activityid: p.ID })
    data2 = _data2
    window.open(`https://cdn.hterobot.com/diffeditor/index.html?code1=${encode(data[1], true)}&code2=${encode(data2[1], true)}&language=${language}&name1=${encode(body.name, true)}&name2=${encodeURI(body2.name)}`)
  } else {
    window.open(`https://cdn.hterobot.com/diffeditor/index.html?code1=${encode(data[1]), true}&language=${language}&name1=${encode(body.name)}`)
  }
}


async function download2() {
  const act: (string | number | undefined)[][] = [
    ["#", "用户名称", "提交时间", "总分"],
  ];

  const _act = body3.value.map((v, k) => {
    return [
      k + 1,
      `${v.name}${v.xingming ? v.name ===
        v.xingming ? '' : `(${v.xingming})` : ''}`,
      TimeYH(v.createdAt),
      v.df,
    ];
  });
  getExceltodownload(act.concat(_act), `比赛成绩表`);
}


async function getcode(params: any, index: Studycodemodel.Imatchquestion) {
  const { userid, name } = params

  // 权限检查：只有管理员或本人才能查看代码
  if (!isAdmin.value && !iswatchcode.value && userid !== user.value?.ID) {
    ElMessage.error('没有权限查看此代码')
    return
  }

  const questionid = index.ID
  const activityid = p.ID
  const teamid = activity.teamid || team.value[0]?.ID
  if (index.type === '代码') {
    try {
      const { rows } = await asyncteamselectmatchuserquestion({
        userid,
        questionid,
        activityid,
        teamid
      })
      if (rows.length) {
        const { context, language } = rows[0]
        window.open(`https://cdn.hterobot.com/diffeditor/index.html?code1=${encode(String(context), true)}&language=${language}&name1=${encode(name + ' ' + index.name, true)}`)
      } else {
        ElMessage.error('没有找到此题')
      }
    } catch (e) {
      ElMessage.error(e as any)
    }
  } else {
    ElMessage.error('此题不是代码题')
  }



}



</script>

<style scoped>
.m-0 {
  background-position-x: right;
  background-position-y: top;
  background-repeat: no-repeat;
}

.co-1 {
  padding-left: 48px;
  padding-right: 48px;
  background-position-x: right;
  background-position-y: top;
  background-repeat: no-repeat;
}

.title {
  height: 48px;
  color: #fff;
  font-size: 36px;
  line-height: 48px;
  margin-top: 48px;
}

.main {
  background-color: #454545;
  margin-top: 24px;
  border-radius: 2px;
  background-image: url(https://cdn.hterobot.com/JOY/oj_1_1/HGKJ_OJ_1.0_bisaipaiming_%20BG.png);
  background-position-x: center;
  background-repeat: no-repeat;
  background-size: contain;
  padding-bottom: 35px;
}

.time {
  background: #1f1f1f;
  box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.18);
  border-radius: 36px;
  width: 261px;
  height: 30px;
  font-size: 14px;
  line-height: 30px;
  color: #ffffff;
  padding-left: 24px;
  margin-top: 12px;
  margin-bottom: 12px;
}

.nav-item {
  margin-right: 10px;
  /* border-left: 1px solid #dcdfe6;
  border-right: 1px solid #dcdfe6; */
  border-top: 1px solid #dcdfe6;
  padding-top: 5px;
  font-size: 18px;
  border-top-left-radius: 0.25rem;
  border-top-right-radius: 0.25rem;
  line-height: 34px;
  background-color: #ffffff;
  width: 180px;
  text-align: center;
  border-bottom: 1px solid #dee2e6;
}

.nav-tabs .nav-item:hover {
  border-top: 6px solid var(--color-cheng);
  padding-top: 0px;
  border-color: var(--color-cheng);
  border-bottom-color: #fff;

  border-bottom-width: 1;
}

.nav-link {
  color: #000000;
}

.nav-tabs .nav-item-active {
  border-top: 6px solid var(--color-cheng);
  padding-top: 0px;
  border-color: var(--color-cheng);
  border-bottom-color: #fff;
  border-bottom-width: 1;
}

.nav-link {
  cursor: pointer;
  font-size: 18px;
  line-height: 28px;
  border: none !important;
}

.span1 {
  border-radius: 50%;
  display: inline-block;
  width: 25px;
  height: 25px;
  text-align: center;
  line-height: 26px;
  margin-right: 4px;
  font-size: 12px;
}

.cu:hover {
  text-decoration: underline;
}

.div1 {
  height: 24px;
  padding-left: 12px;
  padding-right: 12px;
  line-height: 24px;
  border-radius: 4px;
  text-align: center;
}

#activitydata .RuntimeError {
  background-color: blueviolet;
  color: #fff;
}

#activitydata .RuntimeError {
  background-color: blueviolet;
  color: #fff;
}

.WrongAnswer {
  background-color: #f5ac50;
  color: #ffffff;
}

.nav-tabs {
  border-width: 0;
}

.a-down {
  color: var(--cloor-43);
  padding-left: 10px;
  padding-right: 10px;
  text-decoration: underline;
  cursor: pointer;
}

.a-down:hover {
  color: var(--color-cheng);
}

.a-down:active {
  color: var(--color-cheng);
}

.el-collapse-item {
  margin-bottom: 24px;
  border: 1px solid #d9d9d9;
  border-radius: 2px;
}
</style>
<style>
#activitydata .el-collapse {
  --el-collapse-border-color: none;
  --el-collapse-header-height: 48px;
  --el-collapse-header-text-color: var(--colo-43);

  --el-collapse-header-bg-color: #fafafa;
  --el-collapse-content-bg-color: #fff;
  --el-collapse-content-font-color: none;
  border-width: 0;
}

#activitydata .el-collapse-item__header:hover {
  --el-collapse-header-bg-color: #f5f5f5;
}

#activitydata .el-collapse-item__header.is-active {
  --el-collapse-header-bg-color: var(--color-43);
  --el-collapse-header-text-color: #F5F5F5
}

#activitydata .el-collapse-item__header.is-active .table {
  color: var(--el-collapse-header-text-color);
}


#activitydata .el-collapse-item__header {
  border-radius: 2px;
  overflow: hidden;
}

#activitydata .el-collapse-item__content {
  padding: 0.5rem;
}

#activitydata .el-pager li {
  margin: 0;
}

#activitydata .el-table-column .cell {
  min-width: 120px;
}

.alert {
  flex-direction: row;
  justify-content: center;
  align-items: center;
  padding: 12px;
  gap: 12px;

  width: 480px;
  height: 52px;
  background: #F5F5F5;
  /* Layer_line */

  border: 1px solid rgba(0, 0, 0, 0.06);
  border-radius: 4px;
  margin: 24px auto;
  color: #000;
  font-size: 16px;
}
</style>
